home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 22 / AACD 22.iso / AACD / Online / Apache / lib / php / DB.php next >
Encoding:
PHP Script  |  2001-03-06  |  15.4 KB  |  523 lines

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4.0                                                      |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997, 1998, 1999, 2000 The PHP Group                   |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 of the PHP license,      |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Stig Bakken <ssb@fast.no>                                   |
  17. // |                                                                      |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // $Id: DB.php,v 1.34 2000/10/15 09:02:54 ssb Exp $
  21. //
  22. // Database independent query interface.
  23. //
  24.  
  25. require_once "PEAR.php";
  26.  
  27. /*
  28.  * The method mapErrorCode in each DB_dbtype implementation maps
  29.  * native error codes to one of these.
  30.  *
  31.  * If you add an error code here, make sure you also add a textual
  32.  * version of it in DB::errorMessage().
  33.  */
  34. define("DB_OK",                          0);
  35. define("DB_ERROR",                     -1);
  36. define("DB_ERROR_SYNTAX",              -2);
  37. define("DB_ERROR_CONSTRAINT",          -3);
  38. define("DB_ERROR_NOT_FOUND",           -4);
  39. define("DB_ERROR_ALREADY_EXISTS",      -5);
  40. define("DB_ERROR_UNSUPPORTED",         -6);
  41. define("DB_ERROR_MISMATCH",            -7);
  42. define("DB_ERROR_INVALID",             -8);
  43. define("DB_ERROR_NOT_CAPABLE",         -9);
  44. define("DB_ERROR_TRUNCATED",          -10);
  45. define("DB_ERROR_INVALID_NUMBER",     -11);
  46. define("DB_ERROR_INVALID_DATE",       -12);
  47. define("DB_ERROR_DIVZERO",            -13);
  48. define("DB_ERROR_NODBSELECTED",       -14);
  49. define("DB_ERROR_CANNOT_CREATE",      -15);
  50. define("DB_ERROR_CANNOT_DELETE",      -16);
  51. define("DB_ERROR_CANNOT_DROP",        -17);
  52. define("DB_ERROR_NOSUCHTABLE",        -18);
  53. define("DB_ERROR_NOSUCHFIELD",        -19);
  54. define("DB_ERROR_NEED_MORE_DATA",     -20);
  55. define("DB_ERROR_NOT_LOCKED",         -21);
  56. define("DB_ERROR_VALUE_COUNT_ON_ROW", -22);
  57.  
  58.  
  59. /*
  60.  * Warnings are not detected as errors by DB::isError(), and are not
  61.  * fatal.  You can detect whether an error is in fact a warning with
  62.  * DB::isWarning().
  63.  */
  64. define("DB_WARNING",             -1000);
  65. define("DB_WARNING_READ_ONLY",   -1001);
  66.  
  67.  
  68. /*
  69.  * These constants are used when storing information about prepared
  70.  * statements (using the "prepare" method in DB_dbtype).
  71.  *
  72.  * The prepare/execute model in DB is mostly borrowed from the ODBC
  73.  * extension, in a query the "?" character means a scalar parameter.
  74.  * There is one extension though, a "*" character means an opaque
  75.  * parameter.  An opaque parameter is simply a file name, the real
  76.  * data are in that file (useful for stuff like putting uploaded files
  77.  * into your database).
  78.  */
  79. define("DB_PARAM_SCALAR",           1);
  80. define("DB_PARAM_OPAQUE",           2);
  81.  
  82.  
  83. /*
  84.  * These constants define different ways of returning binary data
  85.  * from queries.  Again, this model has been borrowed from the ODBC
  86.  * extension.
  87.  *
  88.  * DB_BINMODE_PASSTHRU sends the data directly through to the browser
  89.  * when data is fetched from the database.
  90.  * DB_BINMODE_RETURN lets you return data as usual.
  91.  * DB_BINMODE_CONVERT returns data as well, only it is converted to
  92.  * hex format, for example the string "123" would become "313233".
  93.  */
  94. define("DB_BINMODE_PASSTHRU",       1);
  95. define("DB_BINMODE_RETURN",         2);
  96. define("DB_BINMODE_CONVERT",        3);
  97.  
  98.  
  99.  
  100. /**
  101.  * This is a special constant that tells DB the user hasn't specified
  102.  * any particular get mode, so the default should be used.
  103.  */
  104. define('DB_FETCHMODE_DEFAULT', 0);
  105. /**
  106.  * Column data indexed by numbers, ordered from 0 and up
  107.  */
  108. define('DB_FETCHMODE_ORDERED', 1);
  109. /**
  110.  * Column data indexed by column names
  111.  */
  112. define('DB_FETCHMODE_ASSOC',   2);
  113. /**
  114.  * For multi-dimensional results: normally the first level of arrays
  115.  * is the row number, and the second level indexed by column number or name.
  116.  * DB_FETCHMODE_FLIPPED switches this order, so the first level of arrays
  117.  * is the column name, and the second level the row number.
  118.  */
  119. define('DB_FETCHMODE_FLIPPED', 4);
  120.  
  121. /* for compatibility */
  122. define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED);
  123. define('DB_GETMODE_ASSOC',   DB_FETCHMODE_ASSOC);
  124. define('DB_GETMODE_FLIPPED', DB_FETCHMODE_FLIPPED);
  125.  
  126. /**
  127.  * The main "DB" class is simply a container class with some static
  128.  * methods for creating DB objects as well as some utility functions
  129.  * common to all parts of DB.
  130.  *
  131.  * The object model of DB is as follows (indentation means inheritance):
  132.  *
  133.  * DB           The main DB class.  This is simply a utility class
  134.  *              with some "static" methods for creating DB objects as
  135.  *              well as common utility functions for other DB classes.
  136.  * 
  137.  * DB_common    The base for each DB implementation.  Provides default
  138.  * |            implementations (in OO lingo virtual methods) for
  139.  * |            the actual DB implementations as well as a bunch of
  140.  * |            query utility functions.
  141.  * |
  142.  * +-DB_mysql   The DB implementation for MySQL.  Inherits DB_common.
  143.  *              When calling DB::factory or DB::connect for MySQL
  144.  *              connections, the object returned is an instance of this
  145.  *              class.
  146.  *
  147.  * @version  2
  148.  * @author   Stig Bakken <ssb@fast.no>
  149.  * @since    PHP 4.0
  150.  */
  151. class DB {
  152.     /**
  153.      * Create a new DB object for the specified database type
  154.      *
  155.      * @param $type string database type, for example "mysql"
  156.      *
  157.      * @return object a newly created DB object, or a DB error code on
  158.      * error
  159.      */
  160.     function &factory($type) {
  161.         @include_once("DB/${type}.php");
  162.         $classname = 'DB_' . $type;
  163.         $obj = @new $classname;
  164.         if (!$obj) {
  165.             return new DB_Error(DB_ERROR_NOT_FOUND);
  166.         }
  167.         return $obj;
  168.     }
  169.  
  170.     /**
  171.      * Create a new DB object and connect to the specified database
  172.      *
  173.      * @param $dsn string "data source name", see the DB::parseDSN
  174.      * method for a description of the dsn format.
  175.      *
  176.      * @param $persistent bool whether this connection should be
  177.      * persistent.  Ignored if the backend extension does not support
  178.      * persistent connections.
  179.      *
  180.      * @return object a newly created DB object, or a DB error code on
  181.      * error
  182.      */
  183.     function &connect($dsn, $persistent = false) {
  184.         $dsninfo = DB::parseDSN($dsn);
  185.         $type = $dsninfo['phptype'];
  186.         @include_once("DB/${type}.php");
  187.         $classname = 'DB_' . $type;
  188.         $obj = @new $classname;
  189.         if (!$obj) {
  190.             return new DB_Error(DB_ERROR_NOT_FOUND);
  191.         }
  192.         $err = $obj->connect($dsninfo, $persistent);
  193.         if (DB::isError($err)) {
  194.             return $err;
  195.         }
  196.         return $obj;
  197.     }
  198.  
  199.     /**
  200.      * Return the DB API version
  201.      *
  202.      * @return int the DB API version number
  203.      */
  204.     function apiVersion() {
  205.         return 2;
  206.     }
  207.  
  208.     /**
  209.      * Tell whether a result code from a DB method is an error
  210.      *
  211.      * @param $value int result code
  212.      *
  213.      * @return bool whether $value is an error
  214.      */
  215.     function isError($value) {
  216.         return is_object($value) &&
  217.             (get_class($value) == "db_error" ||
  218.              is_subclass_of($value, "db_error"));
  219.     }
  220.  
  221.     /**
  222.      * Tell whether a result code from a DB method is a warning.
  223.      * Warnings differ from errors in that they are generated by DB,
  224.      * and are not fatal.
  225.      *
  226.      * @param $value mixed result value
  227.      *
  228.      * @return bool whether $value is a warning
  229.      */
  230.     function isWarning($value) {
  231.         return is_object($value) &&
  232.             (get_class($value) == "db_warning" ||
  233.              is_subclass_of($value, "db_warning"));
  234.     }
  235.  
  236.     /**
  237.      * Return a textual error message for a DB error code
  238.      *
  239.      * @param $value int error code
  240.      *
  241.      * @return string error message, or false if the error code was
  242.      * not recognized
  243.      */
  244.     function errorMessage($value) {
  245.         if (!isset($errorMessages)) {
  246.             $errorMessages = array(
  247.                 DB_ERROR                    => "unknown error",
  248.                 DB_ERROR_ALREADY_EXISTS     => "already exists",
  249.                 DB_ERROR_CANNOT_CREATE      => "can not create",
  250.                 DB_ERROR_CANNOT_DELETE      => "can not delete",
  251.                 DB_ERROR_CANNOT_DROP        => "can not drop",
  252.                 DB_ERROR_CONSTRAINT         => "constraint violation",
  253.                 DB_ERROR_DIVZERO            => "division by zero",
  254.                 DB_ERROR_INVALID            => "invalid",
  255.                 DB_ERROR_INVALID_DATE       => "invalid date or time",
  256.                 DB_ERROR_INVALID_NUMBER     => "invalid number",
  257.                 DB_ERROR_MISMATCH           => "mismatch",
  258.                 DB_ERROR_NODBSELECTED       => "no database selected",
  259.                 DB_ERROR_NOSUCHFIELD        => "no such field",
  260.                 DB_ERROR_NOSUCHTABLE        => "no such table",
  261.                 DB_ERROR_NOT_CAPABLE        => "DB backend not capable",
  262.                 DB_ERROR_NOT_FOUND          => "not found",
  263.                 DB_ERROR_NOT_LOCKED         => "not locked",
  264.                 DB_ERROR_SYNTAX             => "syntax error",
  265.                 DB_ERROR_UNSUPPORTED        => "not supported",
  266.                 DB_ERROR_VALUE_COUNT_ON_ROW => "value count on row",
  267.                 DB_OK                       => "no error",
  268.                 DB_WARNING                  => "unknown warning",
  269.                 DB_WARNING_READ_ONLY        => "read only"
  270.             );
  271.         }
  272.         if (DB::isError($value)) {
  273.             $value = $value->code;
  274.         }
  275.         return $errorMessages[$value];
  276.     }
  277.  
  278.     /**
  279.      * Parse a data source name
  280.      *
  281.      * @param $dsn string Data Source Name to be parsed
  282.      *
  283.      * @return array an associative array with the following keys:
  284.      * <dl>
  285.      *  <dt>phptype</dt>
  286.      *  <dd>Database backend used in PHP (mysql, odbc etc.)</dd>
  287.      *  <dt>dbsyntax</dt>
  288.      *  <dd>Database used with regards to SQL syntax etc.</dd>
  289.      *  <dt>protocol</dt>
  290.      *  <dd>Communication protocol to use (tcp, unix etc.)</dd>
  291.      *  <dt>hostspec</dt>
  292.      *  <dd>Host specification (hostname[:port])</dd>
  293.      *  <dt>database</dt>
  294.      *  <dd>Database to use on the DBMS server</dd>
  295.      *  <dt>username</dt>
  296.      *  <dd>User name for login</dd>
  297.      *  <dt>password</dt>
  298.      *  <dd>Password for login</dd>
  299.      * </dl>
  300.      * </p>
  301.      *
  302.      * <p>
  303.      * The format of the supplied DSN is in its fullest form:
  304.      * <ul>
  305.      *  <li>phptype(dbsyntax)://username:password@protocol+hostspec/database</li>
  306.      * </ul>
  307.      * Most variations are allowed:
  308.      * <ul>
  309.      *  <li>phptype://username:password@protocol+hostspec/database</li>
  310.      *  <li>phptype://username:password@hostspec/database</li>
  311.      *  <li>phptype://username:password@hostspec</li>
  312.      *  <li>phptype://hostspec/database</li>
  313.      *  <li>phptype://hostspec</li>
  314.      *  <li>phptype(dbsyntax)</li>
  315.      *  <li>phptype</li>
  316.      * </ul>
  317.      * </p>
  318.      *
  319.      * @return bool FALSE is returned on error
  320.      */
  321.     function parseDSN($dsn) {
  322.         if (is_array($dsn))
  323.             return $dsn;
  324.         
  325.         $parsed = array(
  326.             'phptype'  => false,
  327.             'dbsyntax' => false,
  328.             'protocol' => false,
  329.             'hostspec' => false,
  330.             'database' => false,
  331.             'username' => false,
  332.             'password' => false
  333.         );
  334.         if (preg_match('|^([^:]+)://|', $dsn, $arr)) {
  335.             $dbtype = $arr[1];
  336.             $dsn = preg_replace('|^[^:]+://|', '', $dsn);
  337.             // match "phptype(dbsyntax)"
  338.             if (preg_match('|^([^\(]+)\((.+)\)$|', $dbtype, $arr)) {
  339.                 $parsed['phptype'] = $arr[1];
  340.                 $parsed['dbsyntax'] = $arr[2];
  341.             } else {
  342.                 $parsed['phptype'] = $dbtype;
  343.             }
  344.         } else {
  345.             // match "phptype(dbsyntax)"
  346.             if (preg_match('|^([^\(]+)\((.+)\)$|', $dsn, $arr)) {
  347.                 $parsed['phptype'] = $arr[1];
  348.                 $parsed['dbsyntax'] = $arr[2];
  349.             } else {
  350.                 $parsed['phptype'] = $dsn;
  351.             }
  352.             return $parsed;
  353.         }
  354.  
  355.         if (preg_match('|^(.*)/([^/]+)/?$|', $dsn, $arr)) {
  356.             $parsed['database'] = $arr[2];
  357.             $dsn = $arr[1];
  358.         }
  359.  
  360.         if (preg_match('|^([^:]+):([^@]+)@?(.*)$|', $dsn, $arr)) {
  361.             $parsed['username'] = $arr[1];
  362.             $parsed['password'] = $arr[2];
  363.             $dsn = $arr[3];
  364.         } elseif (preg_match('|^([^:]+)@(.*)$|', $dsn, $arr)) {
  365.             $parsed['username'] = $arr[1];
  366.             $dsn = $arr[2];
  367.         }
  368.         
  369.         if (preg_match('|^([^\+]+)\+(.*)$|', $dsn, $arr)) {
  370.             $parsed['protocol'] = $arr[1];
  371.             $dsn = $arr[2];
  372.         }
  373.  
  374.         if (!$parsed['database'])
  375.             $dsn = preg_replace('|/+$|', '', $dsn);
  376.  
  377.         $parsed['hostspec'] = urldecode($dsn);
  378.  
  379.         if (!$parsed['dbsyntax']) {
  380.             $parsed['dbsyntax'] = $parsed['phptype'];
  381.         }
  382.  
  383.         return $parsed;
  384.     }
  385. }
  386.  
  387. /**
  388.  * This class implements a wrapper for a DB result set.
  389.  * A new instance of this class will be returned by the DB implementation
  390.  * after processing a query that returns data.
  391.  *
  392.  * @author Stig Bakken <ssb@fast.no>
  393.  */
  394. class DB_result {
  395.  
  396.     var $dbh;
  397.     var $result;
  398.  
  399.     /**
  400.      * DB_result constructor.
  401.      * @param   $dbh    DB object reference
  402.      * @param   $result result resource id
  403.      */
  404.     function DB_result(&$dbh, $result) {
  405.         $this->dbh = &$dbh;
  406.         $this->result = $result;
  407.     }
  408.  
  409.     /**
  410.      * Fetch and return a row of data.
  411.      * @return  array   a row of data, or false on error
  412.      */
  413.     function fetchRow($fetchmode = DB_FETCHMODE_DEFAULT) {
  414.         if ($fetchmode == DB_FETCHMODE_DEFAULT) {
  415.             $fetchmode = $this->dbh->fetchmode;
  416.         }
  417.         return $this->dbh->fetchRow($this->result, $fetchmode);
  418.     }
  419.  
  420.     /**
  421.      * Fetch a row of data into an existing array.
  422.      *
  423.      * @param   $arr    reference to data array
  424.      * @return  int     error code
  425.      */
  426.     function fetchInto(&$arr, $fetchmode = DB_FETCHMODE_DEFAULT) {
  427.         if ($fetchmode == DB_FETCHMODE_DEFAULT) {
  428.             $fetchmode = $this->dbh->fetchmode;
  429.         }
  430.         return $this->dbh->fetchInto($this->result, $arr, $fetchmode);
  431.     }
  432.  
  433.     /**
  434.      * Get the the number of columns in a result set.
  435.      *
  436.      * @return int the number of columns, or a DB error code
  437.      */
  438.     function numCols() {
  439.         return $this->dbh->numCols($this->result);
  440.     }
  441.  
  442.     /**
  443.      * Frees the resources allocated for this result set.
  444.      * @return  int     error code
  445.      */
  446.     function free() {
  447.         $err = $this->dbh->freeResult($this->result);
  448.         if (DB::isError($err)) {
  449.             return $err;
  450.         }
  451.         $this->result = false;
  452.         return true;
  453.     }
  454. }
  455.  
  456. /**
  457.  * DB_Error implements a class for reporting portable database error
  458.  * messages.
  459.  *
  460.  * @author Stig Bakken <ssb@fast.no>
  461.  */
  462. class DB_Error extends PEAR_Error {
  463.     /**
  464.      * DB_Error constructor.
  465.      *
  466.      * @param $code mixed DB error code, or string with error message.
  467.      * @param $mode int what "error mode" to operate in
  468.      * @param $level what error level to use for $mode & PEAR_ERROR_TRIGGER
  469.      * @param $debuginfo additional debug info, such as the last query
  470.      *
  471.      * @access public
  472.      *
  473.      * @see PEAR_Error
  474.      */
  475.     function DB_Error($code = DB_ERROR,
  476.                       $mode = PEAR_ERROR_RETURN,
  477.                       $level = E_USER_NOTICE,
  478.                       $debuginfo = null) {
  479.         if (is_int($code)) {
  480.             $this->PEAR_Error("DB Error: " . DB::errorMessage($code), $code, $mode, $level, $debuginfo);
  481.         } else {
  482.             $this->PEAR_Error("DB Error: $code", 0, $mode, $level, $debuginfo);
  483.         }
  484.     }
  485. }
  486.  
  487. /**
  488.  * DB_Warning implements a class for reporting portable database
  489.  * warning messages.
  490.  *
  491.  * @author Stig Bakken <ssb@fast.no>
  492.  */
  493. class DB_Warning extends PEAR_Error {
  494.     /**
  495.      * DB_Warning constructor.
  496.      *
  497.      * @param $code mixed DB error code, or string with error message.
  498.      * @param $mode int what "error mode" to operate in
  499.      * @param $level what error level to use for $mode == PEAR_ERROR_TRIGGER
  500.      * @param $debuginfo additional debug info, such as the last query
  501.      *
  502.      * @access public
  503.      *
  504.      * @see PEAR_Error
  505.      */
  506.     function DB_Warning($code = DB_WARNING,
  507.                         $mode = PEAR_ERROR_RETURN,
  508.                         $level = E_USER_NOTICE,
  509.                         $debuginfo = null) {
  510.         if (is_int($code)) {
  511.             $this->PEAR_Error("DB Warning: " . DB::errorMessage($code), $code, $mode, $level, $debuginfo);
  512.         } else {
  513.             $this->PEAR_Error("DB Warning: $code", 0, $mode, $level, $debuginfo);
  514.         }
  515.     }
  516. }
  517.  
  518. // Local variables:
  519. // tab-width: 4
  520. // c-basic-offset: 4
  521. // End:
  522. ?>
  523.